package com.zkx.laolaiyi.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.zkx.laolaiyi.constant.ExceptionMsgConstant;
import com.zkx.laolaiyi.constant.RoleTypeConstants;
import com.zkx.laolaiyi.entity.Admin;
import com.zkx.laolaiyi.entity.LoginAdmin;
import com.zkx.laolaiyi.entity.LoginUser;
import com.zkx.laolaiyi.entity.User;
import com.zkx.laolaiyi.exceptions.RoleTypeException;
import com.zkx.laolaiyi.mapper.AdminMapper;
import com.zkx.laolaiyi.mapper.UserMapper;
import com.zkx.laolaiyi.utils.EncryptedLambdaQueryWrapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Objects;

/**
 * SpringSecurity会把username传到这个实现类
 */
@RequiredArgsConstructor
@Service
@Slf4j
public class UserDetailsServiceImpl implements UserDetailsService {
    private final UserMapper userMapper;
    private final AdminMapper adminMapper;

    /**
     * 这个方法不用，因为这个方法是常规的，不满足需求。用下面那个含有role的。
     * @param username the username identifying the user whose data is required.
     * @return
     * @throws UsernameNotFoundException
     */
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(User::getUsername, username);
        User user = userMapper.selectOne(wrapper);
        if (Objects.isNull(user)) {
            log.error("没有找到username：{}", username);
            throw new UsernameNotFoundException(ExceptionMsgConstant.NOT_FOUND_USER_BY_USERNAME);
        }
        return new LoginUser(user);
    }

    /**
     * 根据role，去不同的角色表中查数据
     * @param username
     * @param role
     * @return
     * @throws UsernameNotFoundException
     * @throws RoleTypeException
     */
    public UserDetails loadUserByUsernameAndRole(String username, String role) throws UsernameNotFoundException, RoleTypeException {
        if (RoleTypeConstants.ADMIN.equals(role)) {
            // 管理员身份验证
            LambdaQueryWrapper<Admin> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(Admin::getUsername, username);
            Admin admin = adminMapper.selectOne(wrapper);
            if (Objects.isNull(admin)) {
                log.error("没有找到admin的username：{}", username);
                throw new UsernameNotFoundException(ExceptionMsgConstant.NOT_FOUND_USER_BY_USERNAME);
            }
            return new LoginAdmin(admin);
        } else if (RoleTypeConstants.USER.equals(role)) {
            // 普通用户身份验证
//            LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
//            wrapper.eq(User::getUsername, username);
//            User user = userMapper.selectOne(wrapper);

            // 由于使用了MybatisPlus的自动加解密功能，所以需要重新实现一个LambdaQueryWrapper，进行自动加密。
            EncryptedLambdaQueryWrapper<User> wrapper = new EncryptedLambdaQueryWrapper<>();
            wrapper.encryptedEq(User::getUsername, username);
            User user = userMapper.selectOne(wrapper);
            if (Objects.isNull(user)) {
                log.error("没有找到user的username：{}", username);
                throw new UsernameNotFoundException(ExceptionMsgConstant.NOT_FOUND_USER_BY_USERNAME);
            }
            return new LoginUser(user);
        }
        // 逻辑上不可能为null
        throw new RoleTypeException(ExceptionMsgConstant.ROLE_TYPE_EXCEPTION);
    }
}
